create or replace function pgds_gen_bytea(len int) returns bytea as $$
declare message bytea;
declare i int;
begin
        i := 0;
        message := '';
        loop
                message := message || ' ';
                message := set_byte(message, i, (0 + (random()*255)::int));
                i := i + 1;
                if i >= len then
                        exit;
                end if;
        end loop;
	return message;
end;
$$ language plpgsql;

create or replace function pgds_gen_text(len int) returns text as $$
declare message text;
declare i int;
begin
        i := 0;
        message := '';
        loop
                message := message || chr(97 + (random() * 25)::int);
                i := i + 1;
                if i >= len then
                        exit;
                end if;
        end loop;
	return message;
end;
$$ language plpgsql;

create or replace function pgds_test_sym(pw_len int, data_len int, rounds int) returns int as $$
declare message bytea;
declare enc_message bytea;
declare dec_message bytea;
declare salt bytea;
declare iv bytea;
declare pw text;
declare public_key text;
declare c record;
declare d record;
begin
	pw := pgds_gen_text(pw_len);
        salt := pgds_gen_bytea(8);
        iv := pgds_gen_bytea(32);
        message := pgds_gen_bytea(data_len);
        for c in select alg from regexp_split_to_table('des-cbc bf-cbc idea-cbc aes128-cbc aes192-cbc aes256-cbc des-ecb bf-ecb idea-ecb aes128-ecb aes192-ecb aes256-ecb', E'\\s+') as alg loop
		for d in select alg from regexp_split_to_table('md2 md4 md5 sha1 sha224 sha256 sha384 sha512', E'\\s+') as alg loop
			enc_message := encrypt(c.alg, pw, d.alg, rounds, salt, iv, message);
			if enc_message = '' then
				return 1;
			end if;
			if enc_message = message then
				return 2;
			end if;
			dec_message := decrypt(c.alg, pw, d.alg, rounds, salt, iv, enc_message);
			if dec_message = '' then
				return 3;
			end if;
			if dec_message <> message then
				raise exception '%/% [%]  <>   [%]', c.alg, d.alg, dec_message, message;
				return 4;
			end if;
		end loop;
        end loop;
        return 0;
end;
$$ language plpgsql;


select * from (
      select 1 as test, pgds_test_sym(8, 128, 1) as rc
union select 2 as test, pgds_test_sym(8, 256, 1) as rc
union select 3 as test, pgds_test_sym(8, 384, 2) as rc
union select 4 as test, pgds_test_sym(12, 512, 3) as rc
union select 5 as test, pgds_test_sym(14, 1024, 4) as rc
union select 6 as test, pgds_test_sym(16, 2048, 4) as rc
union select 7 as test, pgds_test_sym(16, 4096, 5) as rc
union select 8 as test, pgds_test_sym(18, 8192, 5) as rc
union select 9 as test, pgds_test_sym(18, 16384, 6) as rc
union select 10 as test, pgds_test_sym(32, 131072, 9) as rc
) s1 order by s1.test
;

drop function pgds_test_sym(pw_len int, data_len int, rounds int);
drop function pgds_gen_text(len int);
drop function pgds_gen_bytea(len int);

